<?php
class Pageley_Imaging_Image {
    private $width;
    private $height;
    private $resource;
    
    public function __construct($width, $height, $resource = null) {
        $this->width = $width;
        $this->height = $height;
        if($resource === null) {
            $resource = imagecreatetruecolor($width, $height);
            imagealphablending($resource, false);
            $transparentColor = Pageley_Imaging_Brush_Color::$TRANSPARENT;
            $transparentId = $transparentColor->getColorId($resource);
            imagecolortransparent($resource, $transparentId);
            imagefill($resource, 0, 0, $transparentId);
            imagealphablending($resource, true);
            $this->resource = $resource;
        } else {
            $this->resource = $resource;
        }
    }
    
    public static function fromFile($file) {
        $dimensions = getimagesize($file->getPath());
        if(!$dimensions) {
            throw new Pageley_Util_IoException("'" . $file->getPath() . "' is not a valid image.");
        }
        $width = $dimensions[0];
        $height = $dimensions[1];
        $mimeType = $dimensions["mime"];
        $resource = null;
        if($mimeType == "image/jpeg") {
            $resource = imagecreatefromjpeg($file->getPath());
        } else if($mimeType == "image/png") {
            $resource = imagecreatefrompng($file->getPath());
        } else if($mimeType == "image/gif") {
            $resource = imagecreatefromgif($file->getPath());
        } else {
            throw new Pageley_Util_IoException("Unsupported image type: " . $mimeType);
        }
        return new Pageley_Imaging_Image($width, $height, $resource);
    }

    public function toFile($file, $mimeType) {
        $fileName = $file->getPath();
        $success = false;
        if($mimeType == "image/jpeg") {
            $success = imagejpeg($this->resource, $fileName, 90);
        } else if($mimeType == "image/gif") {
            $success = imagegif($this->resource, $fileName);
        } else if($mimeType == "image/png") {
            imagealphablending($this->resource, false);
            imagesavealpha($this->resource, true);
            $success = imagepng($this->resource, $fileName);
            imagesavealpha($this->resource, false);
            imagealphablending($this->resource, true);
        } else {
            throw new Pageley_Util_IoException("Unsupported image type: " . $mimeType);
        }
        if(!$success) {
            throw new Pageley_Util_IoException("Failed to save image to " . $file);
        }
    }
    
    public function getWidth() {
        return $this->width;
    }
    
    public function getHeight() {
        return $this->height;
    }
    
    public function colorAt($x, $y) {
        $colorId = imagecolorat($this->resource, $x, $y);
        return Pageley_Imaging_Brush_Color::fromColorId($colorId);
    }
    
    public function getResizedImage($width, $height) {
        $sourceWidth = $this->width;
        $sourceHeight = $this->height;
        $x = 0;
        $y = 0;
        if($width != 0 && $height != 0) {
            $sourceProportion = $sourceWidth / $sourceHeight;
            $proportion = $width / $height;
            if($sourceProportion > $proportion) {
                $x = round(($sourceWidth - $width * $sourceHeight / $height) / 2);
            } else {
                $y = round(($sourceHeight - $height * $sourceWidth / $width) / 2);
            }
        } else if($width != 0) {
            $height = round(($sourceHeight * $width) / $sourceWidth);
        } else if($height != 0) {
            $width = round(($sourceWidth * $height) / $sourceHeight);
        } else {
            $width = $sourceWidth;
            $height = $sourceHeight;
        }
        $destination = imagecreatetruecolor($width, $height);
        imagecopyresampled($destination, $this->resource, 0, 0, $x, $y, $width, $height, $sourceWidth - 2 * $x, $sourceHeight -  2 * $y);
        return new Pageley_Imaging_Image($width, $height, $destination);
    }
    
    public function draw($shape, $brush, $x, $y) {
        $shape->draw($brush, $this->resource, $x, $y);
    }
    
    public function getResource() {
        return $this->resource;
    }
    
    public function dispose() {
        if(is_resource($this->resource)) {
            imagedestroy($this->resource);
        }
    }
    
    public function __destruct() {
        $this->dispose();
    }
}